/*
 * HkMediaSystem.cpp
 *
 *  Created on: 2017年8月20日
 *      Author: terry
 */

#include "HkMediaSystem.h"
#include "CLog.h"
#include <algorithm>
#include "AppConfig.h"


namespace av
{


std::string AnsiToUtf8(LPCSTR Ansi)
{
	int WLength = MultiByteToWideChar(CP_ACP, 0, Ansi, -1, NULL, 0);
	LPWSTR pszW = (LPWSTR)_alloca((WLength + 1) * sizeof(WCHAR));
	MultiByteToWideChar(CP_ACP, 0, Ansi, -1, pszW, WLength);

	int ALength = WideCharToMultiByte(CP_UTF8, 0, pszW, -1, NULL, 0, NULL, NULL);
	LPSTR pszA = (LPSTR)_alloca(ALength + 1);
	WideCharToMultiByte(CP_UTF8, 0, pszW, -1, pszA, ALength, NULL, NULL);
	pszA[ALength] = '\0';

	std::string retStr(pszA);

	return retStr;
}

std::string WcharToUtf8(LPCWSTR szUnicode)
{
	int ALength = WideCharToMultiByte(CP_UTF8, 0, szUnicode, -1, NULL, 0, NULL, NULL);
	LPSTR pszA = (LPSTR)_alloca(ALength + 1);
	WideCharToMultiByte(CP_UTF8, 0, szUnicode, -1, pszA, ALength, NULL, NULL);
	pszA[ALength] = '\0';

	std::string retStr(pszA);
	return retStr;
}

std::string Utf8toAnsi(LPCSTR utf8)
{
	int WLength = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, NULL);
	LPWSTR pszW = (LPWSTR)_alloca((WLength + 1) * sizeof(WCHAR));
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, pszW, WLength);
	pszW[WLength] = '\0';

	int ALength = WideCharToMultiByte(CP_ACP, 0, pszW, -1, NULL, 0, NULL, NULL);
	LPSTR pszA = (LPSTR)_alloca(ALength + 1);
	WideCharToMultiByte(CP_ACP, 0, pszW, -1, pszA, ALength, NULL, NULL);
	pszA[ALength] = '\0';

	std::string retStr = pszA;

	return retStr;

	//return pszA;
}

LPCWSTR Utf8toWchar(LPCSTR utf8)
{
	int WLength = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, NULL);
	LPWSTR pszW = (LPWSTR)_alloca((WLength + 1) *sizeof(WCHAR));
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, pszW, WLength);
	pszW[WLength] = '\0';
	return pszW;
}

void STDCALL OrgInfoCallBack(long getResHandle, int *iContinue,
	int iFinish, const char *FileListXML, void *UserData)
{
	HkMediaSystem* pthis = (HkMediaSystem*)UserData;
	pthis->onOrgInfo(getResHandle, iContinue, iFinish, FileListXML);
}





HkMediaSystem::HkMediaSystem():
	m_port(),
	m_loginId(-1),
	m_sink()
{
	Std_Initialize();

	char sdkVersion[1024] = { 0 };
	Std_GetSDKVersion(sdkVersion);
	CLog::info("SDK version:%s\n", sdkVersion);

	bool dumpEnabled = AppConfig::instance().getBool("App.Dump", false);
	CLog::info("dump enabled: %d\n", dumpEnabled);
}

HkMediaSystem::~HkMediaSystem()
{
	close();

	Std_UnInitialize();
}

void HkMediaSystem::setAddress(const std::string& ip, int port)
{
	m_ip = ip;
	m_port = port;
}

void HkMediaSystem::setAccount(const std::string& username, const std::string& password)
{
	m_username = username;
	m_password = password;
}

bool HkMediaSystem::open()
{
	long loginId = Std_Login(m_ip.c_str(), m_port, m_username.c_str(), m_password.c_str());
	if (loginId == -1)
	{
		char desc[1024] = {0};
		Std_GetLastError(desc);
		CLog::warning("failed to login. %s\n", desc);
		return false;
	}

	m_loginId = loginId;

	Std_GetResList(m_loginId, -1, "", OrgInfoCallBack, this);

	return true;
}

void HkMediaSystem::close()
{
	if (m_loginId >= 0)
	{
		Std_Logout(m_loginId);
		m_loginId = -1;
	}
}

bool HkMediaSystem::isOpen()
{
	return m_loginId != -1;
}

bool HkMediaSystem::exist(const std::string& id)
{
	return true;
	//return m_deviceMap.exist(id);
}

bool HkMediaSystem::getDevice(const std::string& id, Device& device)
{
	char cameraInfo[1024] = { 0 };
	long ret = Std_GetCameraInfo(m_loginId, id.c_str(), cameraInfo);
	if (ret == -1)
	{
		return false;
	}

	device.id = id;
	device.name = id;
	device.url = id;
	device.num = id;
	return true;

	//HkDevice hkDevice;
	//if (!m_deviceMap.find(id, hkDevice))
	//{
	//	return false;
	//}

	//device = hkDevice;
	//return true;
}

size_t HkMediaSystem::listDevice(Device* devices, size_t maxSize)
{
	size_t count = std::min(m_deviceMap.size(), maxSize);
	for (size_t i = 0; i < count; ++i)
	{
		std::string id;
		HkDevice hkDevice;
		m_deviceMap.getAt(i, id, hkDevice);

		Device& device = devices[i];

		device = hkDevice;
	}
	return count;
}

MediaChannelPtr HkMediaSystem::create(const std::string& id)
{
	MediaChannelPtr chl;

	HkDevice hkDevice;
	hkDevice.id = id;
	hkDevice.name = id;

	//if (!m_deviceMap.find(id, hkDevice))
	//{
	//	return chl;
	//}

	HkMediaChannel* channel = new HkMediaChannel();
	channel->setDevice(m_loginId, hkDevice.id, hkDevice.name);

	bool dumpEnabled = AppConfig::instance().getBool("App.Dump", false);
	channel->enableDump(dumpEnabled);

	chl.reset(channel);
	return chl;
}

void HkMediaSystem::setSink(MediaSystemSink* sink)
{
	m_sink = sink;
}

void HkMediaSystem::onOrgInfo(long getResHandle, int *iContinue, int iFinish, const char *FileListXML)
{
	std::string xml = Utf8toAnsi(FileListXML);

	/// todo

	*iContinue = true;
}




}